//在开发过程中 一些时候我们声明的函数不仅仅要明确他的数据类型,而且还要考虑这个方法具有很强的可复用性
//实现类型参数化  ==>泛型
//定义一个方法,在方法中不去确定参数到底是什么类型,而是需要使用者来进行传递


interface IObj{
    name: string,
    age: number
}
//不确定用户传递什么类型的参数回来 那么也就不能确定返回值

//类型的参数化

//在定义这个函数的时候, 我们不去决定这些参数的类型
//而是让调用者以参数的形式告诉我们函数的参数应该是什么类型

//泛型函数
//函数中在函数名的后面通过<形参>的形式,接受传递过来的类型
function fn<T=string>(arg:T):T{
     console.log(arg)
    return arg
}


//泛型函数调用
//1通过<类型> 的方式将类型传递给函数
fn<string>("1234")
//2通过类型推导,自动的推导出我们传入变量的类型
//  在这里会推导出他们是字面量类型, 当然字面量类型对我们的函数也是适用的
fn<number>(123)
//引用类型会推导出想要的效果
fn<number[]>([1,2,3])
fn({a:1})
fn([1,2,3])


//通过泛型的形式来确定变量的数据类型
let arr: string[] = ["1","2","3"]
let arr1: Array<string> = ["1","2","3"]
let arr2: Array<number> = [1,2,3,4]

//泛型=>  泛指所有类型